package managers;

import java.io.IOException;

import messages.observer.EventCollectionMessage;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import state.group.events.EventType;
import test.BaseTest;
import test.stubs.ElevatorStub;
import test.stubs.ObserverStub;

import static org.junit.Assert.*;

public class EventTest extends BaseTest {
    
    @BeforeClass
    public static void initSystem() throws IOException
    {
        BaseTest.initSystem();
        
        //shut down the other threads, so that only the Observer Thread is running.
        HallCallManager.shutdown();
    }
    
    @AfterClass
    public static void teardownSystem() throws IOException
    {
        BaseTest.teardownSystem();
    }
    
    private ElevatorStub stub;
    private ObserverStub obs;
    
    @Before
    public void setup() throws IOException
    {
        stub = new ElevatorStub();
        stub.startUp(port);
        stub.start();
        obs = new ObserverStub();
        obs.connect(port);
    }
    
    @After
    public void cleanUp() throws IOException, InterruptedException
    {
        stub.deregister();
        
        obs.close();
        
        //Ensure the list of events is empty
        Thread.sleep(1000);
    }
    
    @Test
    public void testRegistration() throws IOException, InterruptedException
    {
        stub.deregister();
        
        EventCollectionMessage mess = (EventCollectionMessage) obs.readObserver();
        assertEquals(EventType.DeregistrationEvent, mess.getEvents().get(0).getEventType());
        
        stub = new ElevatorStub();
        stub.startUp(port);
        stub.start();
        
        mess = (EventCollectionMessage) obs.readObserver();
        assertEquals(EventType.RegistrationEvent, mess.getEvents().get(0).getEventType());
        
    }
    
    @Test
    public void testFloor() throws IOException, InterruptedException
    {
        
        EventCollectionMessage mess = (EventCollectionMessage) obs.readObserver();
        assertEquals(1, mess.getEvents().size());
        assertEquals(EventType.RegistrationEvent, mess.getEvents().get(0).getEventType());
        
        stub.struct.lastKnownFloor = 2;
        
        mess = (EventCollectionMessage) obs.readObserver();
        assertEquals(EventType.FloorEvent, mess.getEvents().get(0).getEventType());
    }
    
    @Test
    public void testDirection() throws IOException
    {
    	EventCollectionMessage mess = (EventCollectionMessage) obs.readObserver();
        assertEquals(1, mess.getEvents().size());
        assertEquals(EventType.RegistrationEvent, mess.getEvents().get(0).getEventType());
        
        stub.struct.direction = 2;
        
        mess = (EventCollectionMessage) obs.readObserver();
        assertEquals(EventType.DirectionEvent, mess.getEvents().get(0).getEventType());
    }
    
    @Test
    public void testDoor() throws IOException
    {
    	EventCollectionMessage mess = (EventCollectionMessage) obs.readObserver();
        assertEquals(1, mess.getEvents().size());
        assertEquals(EventType.RegistrationEvent, mess.getEvents().get(0).getEventType());
        
        stub.struct.doorOpen = 1;
        
        mess = (EventCollectionMessage) obs.readObserver();
        assertEquals(1, mess.getEvents().size());
        assertEquals(EventType.DoorEvent, mess.getEvents().get(0).getEventType());
    }
    
}
